package cn.springcloud.fix.stomp.utils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

@Data
@Slf4j
public class FtpUtil implements Closeable {

    public final String PATH_PREFIX = "/";

    private String host;

    private int port = 21;

    private String user;

    private String passwd;

    private String encoding = "GBK";

    private final FTPClient ftpClient;

    public FtpUtil() {
        this.ftpClient = new FTPClient();
    }

    public boolean connect() {
        try {
            ftpClient.setConnectTimeout(30 * 60 * 1000);
            ftpClient.connect(host, port);
            ftpClient.login(user, passwd);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setBufferSize(1024 * 1024);
            ftpClient.setControlEncoding(encoding);
            return true;
        } catch (IOException e) {
            log.error("ftp init error" , e);
        }
        return false;
    }

    public boolean upload(String localFilePath, String remotePath, String fileName) throws IOException {
        InputStream in = new BufferedInputStream(new FileInputStream(localFilePath));
        return upload(in, remotePath, fileName);
    }

    public boolean uploadFileUrl(String url, String path, String fileName) throws IOException {
        URL urlString = new URL(url);
        HttpURLConnection httpUrlConnection = (HttpURLConnection) urlString.openConnection();
        InputStream in = httpUrlConnection.getInputStream();
        return upload(in, path, fileName);
    }

    public boolean upload(InputStream is, String remotePath, String fileName) throws IOException {
        try {
            if (!mkdirs(remotePath)) {
                log.error("create dir error:{}" , remotePath);
                return false;
            }
            if (!ftpClient.storeFile(new String(fileName.getBytes(encoding), StandardCharsets.ISO_8859_1), is)) {
                log.error("storeFile error replyCode:{}, path:{}" , ftpClient.getReplyCode(), remotePath);
                return false;
            }
        } finally {
            IOUtils.closeQuietly(is);
        }
        return true;
    }

    public boolean mkdirs(String path) throws IOException {
        if (PATH_PREFIX.equals(path)) return true;

        if (StringUtils.startsWith(path, PATH_PREFIX)) {
            path = path.substring(1);
        }

        ftpClient.changeWorkingDirectory(PATH_PREFIX);

        String[] subDirs = path.split(PATH_PREFIX);
        for (String subDir : subDirs) {
            if (StringUtils.isEmpty(subDir)) {
                continue;
            }
            subDir = new String(subDir.getBytes(encoding), StandardCharsets.ISO_8859_1);
            if (ftpClient.changeWorkingDirectory(subDir)) {
                continue;
            }
            if (!ftpClient.makeDirectory(subDir)) {
                log.error("makeDirectory error: {}" , subDir);
                return false;
            }
            log.info("makeDirectory: {} success" , subDir);
            // if (!ftpClient.sendSiteCommand("chmod 755 " + subDir)) {
            // 	log.error("chmod dir error: {}", subDir);
            // 	return false;
            // }
            if (!ftpClient.changeWorkingDirectory(subDir)) {
                log.error("change dir error: {}" , subDir);
                return false;
            }
        }

        return true;
    }

    @Override
    public void close() {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
            } catch (IOException ioe) {
                log.error("ftp Client disconnect with error:" , ioe);
            }
        }
    }
}
